from django import forms
from django.db import transaction
from django.db.models import Q
from django.http import JsonResponse
from django.shortcuts import render, redirect
from django.urls import reverse

from utils.bootstrap import BootstrapForm
from utils.encrypt import md5
from utils.group import NbSearchGroup, Option
from utils.link import filter_reverse
from utils.pager import Pagination
from utils.response import BaseResponse
from web.models import Customer, Level, TransactionRecord


class CustomerModelForm(BootstrapForm, forms.ModelForm):
    exclude_field_list = ['level']
    confirm_password = forms.CharField(
        label='重复密码',
        widget=forms.PasswordInput(render_value=True),
    )

    class Meta:
        model = Customer
        fields = ['username', 'mobile', 'email', 'password', 'confirm_password', 'level']
        widgets = {
            'password': forms.PasswordInput(render_value=True),
            'level': forms.RadioSelect(attrs={'class': 'form-radio'}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['level'].queryset = Level.objects.filter(active=True)

    def clean_password(self):
        return md5(self.cleaned_data['password'])

    def clean_confirm_password(self):
        password = self.cleaned_data['password']
        confirm_password = md5(self.cleaned_data['confirm_password'])
        if password != confirm_password:
            raise forms.ValidationError('密码不一致')
        return confirm_password


def customer_list(request):
    # 筛选框配置
    search_group = NbSearchGroup(
        request,
        Customer,
        Option('level', is_multi=True, db_condition={'active': True}),  # ForeignKey 类型
    )

    # 搜索框
    keyword = request.GET.get('keyword', '').strip()
    con = Q()
    if keyword:
        con.connector = 'OR'
        con.children.append(('username__contains', keyword))
        con.children.append(('mobile__contains', keyword))
        con.children.append(('level__title__contains', keyword))

    # 1. 获取客户列表，注意以下问题：
    # 1.1 客户是可以删除的，逻辑删除
    # 1.2 级别是可以删除的，关联的客户如何处理？
    #       - 修改级别。删除级别时，检查关联客户，有关联客户，则不能删除。
    #       - 将关联客户的级别统一设置为指定值，例如 NULL
    #       - 不做任何处理（本次业务选择此项）
    queryset = (Customer.objects.filter(con)
                .filter(**search_group.get_condition)  # 筛选框条件
                .filter(active=True).select_related('level').order_by('id'))
    # 分页
    from utils.pager import Pagination
    pager = Pagination(request, queryset)

    customer = {
        'queryset': queryset[pager.item_start:pager.item_end],
        'page_html': pager.html(),
        'keyword': keyword,
        'search_group': search_group,
    }
    return render(request, 'customer_list.html', customer)


def customer_add(request):
    if request.method == 'GET':
        form = CustomerModelForm()
        return render(request, 'form2.html', {'form': form})

    form = CustomerModelForm(request.POST)
    if not form.is_valid():
        return render(request, 'form2.html', {'form': form})

    form.instance.creator_id = request.my_user.id
    form.save()
    return redirect(reverse('customer_list'))


class CustomerEditModelForm(BootstrapForm, forms.ModelForm):
    class Meta:
        model = Customer
        fields = ['username', 'mobile', 'level']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['level'].queryset = Level.objects.filter(active=True)


def customer_edit(request, pk):
    instance = Customer.objects.filter(id=pk).first()
    if request.method == 'GET':
        form = CustomerEditModelForm(instance=instance)
        return render(request, 'form2.html', {'form': form})

    form = CustomerEditModelForm(request.POST, instance=instance)
    if not form.is_valid():
        return render(request, 'form2.html', {'form': form})

    form.save()
    url = filter_reverse(request, 'customer_list')
    return redirect(url)


class CustomerResetModelForm(BootstrapForm, forms.ModelForm):
    confirm_password = forms.CharField(
        label='重复密码',
        widget=forms.PasswordInput(render_value=True),
    )

    class Meta:
        model = Customer
        fields = ['password', 'confirm_password']
        widgets = {
            'password': forms.PasswordInput(render_value=True),
        }

    def clean_password(self):
        return md5(self.cleaned_data['password'])

    def clean_confirm_password(self):
        password = self.cleaned_data['password']
        confirm_password = md5(self.cleaned_data['confirm_password'])
        if password != confirm_password:
            raise forms.ValidationError('密码不一致')
        return confirm_password


def customer_reset(request, pk):
    if request.method == 'GET':
        form = CustomerResetModelForm()
        return render(request, 'form2.html', {'form': form})

    instance = Customer.objects.filter(id=pk).first()
    form = CustomerResetModelForm(request.POST, instance=instance)
    if not form.is_valid():
        return render(request, 'form2.html', {'form': form})

    form.save()
    return redirect(reverse('customer_list'))


def customer_delete(request):
    cid = request.GET.get('cid', 0)
    res = BaseResponse()

    if not cid:
        res.status = False
        res.detail = '请选择要删除的数据'
        return JsonResponse(res.dict)

    if not Customer.objects.filter(id=cid, active=True).exists():
        res.status = False
        res.detail = '要删除的数据不存在'
        return JsonResponse(res.dict)

    Customer.objects.filter(id=cid, active=True).update(active=False)
    res.status = True
    res.detail = '用户已删除'
    return JsonResponse(res.dict)


class CustomerChargeModelForm(BootstrapForm, forms.ModelForm):
    class Meta:
        model = TransactionRecord
        fields = ['charge_type', 'amount', 'memo']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields.get('charge_type').choices = [(1, "充值"), (2, "扣款")]


def customer_charge(request, pk):
    queryset = TransactionRecord.objects.filter(customer_id=pk, customer__active=True).order_by('-id')
    pager = Pagination(request, queryset)
    form = CustomerChargeModelForm()

    # return render(request, 'customer_charge.html', {'pager': pager, 'form': form, 'pk': pk})
    return render(request, 'customer_charge.html', locals())


def customer_charge_add(request, pk):
    form = CustomerChargeModelForm(request.POST)
    if not form.is_valid():
        return JsonResponse({'status': False, 'detail': form.errors})
    try:
        with transaction.atomic():
            # 1. 获取当前操作的用户
            # select_for_update 排它锁，事务结束后释放
            customer_obj = Customer.objects.filter(id=pk, active=True).select_for_update().first()
            amount = form.cleaned_data['amount']
            if form.cleaned_data.get('charge_type') == 2:
                if amount > customer_obj.balance:
                    return JsonResponse(
                        {'status': False, 'detail': {'amount': [f'余额不足。当前余额：{customer_obj.balance}']}})
                amount = -amount
            # 2. 更新余额
            customer_obj.balance += amount
            customer_obj.save()
            # 3. 添加记录
            form.instance.customer = customer_obj
            form.instance.creator_id = request.my_user.id
            form.save()
            return JsonResponse({'status': True})
    except Exception as e:
        return JsonResponse({'status': False, 'detail': {'amount': [f'操作失败，请联系管理员。{e}']}})
